# coding=utf-8
"""
Command Line Client For Kuaipan 

author: ksc (http://blog.geekli.cn)
"""
from __future__ import print_function
import os
import sys
import logging

rlog=logging.getLogger('rlog')

def progress(total,send,width=50):
    '''显示进度条'''
    percent=(send*100)/total
    n=int(percent*width/100)
    bar= n* '='
    bar=bar+((width-n)* ' ')
    
    print("\r[%s] %d%%" % (bar , percent), end=' ')
    
    if percent >= 100:
        print()
    sys.stdout.flush()

class KuaipanCLI():
    
    def __init__(self,api):
        self.api=api
    
    def info(self):
        info=self.api.account_info()
        rlog.debug(info)
        print("%s %s/%s %s%%Used maxfilesize:%s"%(info['user_name'], self.f(info['quota_used']), self.f(info['quota_total'])
            ,round(info['quota_used']*100/float(info['quota_total']),2) ,self.f(info['max_file_size'])))

    def ls(self,file,recursive=False):
        info=self.api.metadata(file)
        #logging.info( info)
        #if path=/,root=kuaipan no  file_id,size,create_time,name,rev
        if (info['path']=='/' and info['root']=='kuaipan') or info['type'] == 'folder':
            if recursive:#递归输出
                self._ls(info['path']);
                return 
            print("%s total %s"%(info['path'],info['files_total']))
            for f in info['files']:
                print("%s\t%s\t%s"%(self.f(f['size']),f['modify_time'],f['name']+('/' if f['type']=='folder' else '')))
                    
        else:
            print( "%s\t%s\t%s"%(self.f(info['size']),info['modify_time'],info['name']))
            
    def _ls(self,path):
        info=self.api.metadata(path)
        root='/' if info['path']=='/' else info['path']+'/';
        for f in info['files']:
            print( "%s\t%s\t%s"%(self.f(f['size']),f['modify_time'],root+f['name']+('/' if f['type']=='folder' else '')))
            if f['type']=='folder':
                self._ls(info['path']+'/'+f['name'])
        
    def mkdir(self,path):
        ret=self.api.create_folder(path)
        logging.info('mkdir:'+path)
        rlog.debug(ret)
        print(ret['msg'])
        
    def rm(self,path):
        '''删除目录或者文件'''
        ret=self.api.delete(path)
        rlog.debug(ret)
        print(ret['msg'])
        
    def mv(self,path, dst):
        ret=self.api.move(path, dst)
        rlog.debug(ret)
        print(ret['msg'])
        
    def cp(self,path, dst):
        if dst[-1]=='/':
            dst=dst+os.path.basename(path)
            
        ret=self.api.copy(path, dst)
        rlog.debug(ret)
        print('ok')
        
    def shares(self, path, access_code=None):
        ret=self.api.shares(path, access_code)
        rlog.debug(ret)
        if not ret.has_key('url'):
            print(ret['msg'])
            return False
        print(ret['url'])
        if ret.has_key('access_code'):
            print ('access_code:%s'%(ret['access_code']))
    
    def upload(self,file,dst='/',deleteAfterUpload=False):
        try:
            fh=open(file,'rb')    
        except Exception as e:
            sys.exit(e)
        fname=os.path.basename(file)
        if dst[-1]=='/':
            fname=dst+fname
        else:
            fname=dst
        print('upload:',fname)
        ret=self.api.upload_file(fname,fh,True)
        fh.close()
        rlog.debug(ret);
        print('send %s'%(self.f(ret['size'])))
        if deleteAfterUpload and ret.get('file_id'):
            os.remove(file)
            print('remove: '+file)
    
    def put(self, path, dst='/', deleteAfterUpload=False):
        '''Upload a directory or file'''
        dst='/' if dst==None else dst    
        if not os.path.exists(path):
            sys.exit('The path:"{0}" doesn\'t exist'.format(path))
        if os.path.isfile(path):
            self.upload(path,dst,deleteAfterUpload)
            return
        #upload directory
        if dst[-1]!='/':
            dst=dst+'/'
        if path[-1]!='/':
            path=path+'/'
        if not self.api.is_exist(dst):
            rlog.info('mkdir '+dst)
            self.api.create_folder(dst)
            
        dst_paths=[]
        file_paths=[]
        for root, dirs, files in os.walk(path, topdown=False):
            if root!=path:
                root=root+'/'
            _root=root[len(path):].replace('\\','/')
            
            for name in dirs:
                _dst=dst+_root+name
                dst_paths.append(_dst)
                  
            for name in files:
                f=os.path.join(root, name)
                _dst=dst+_root+name
                file_paths.append((f,_dst))
                
        #mkdirs 只创建最深层的目录 减少api调用次数
        for v in dst_paths:
            if not self._inpath(v, dst_paths):
                self.mkdir(v)
        #upload file
        for v in file_paths:
            self.upload(v[0],v[1],deleteAfterUpload)

    def _inpath(self, path, paths):    
        for v in paths:
            if self._instr(v,path):
                return True
        return False 
    def _instr(self, str, sub):
        return str[0:len(sub)]==sub and sub!=str
        
    def download(self,path,dst='./'):
        '''下载文件,dst为空则下载到当前目录'''
        ret=self.api.download_file(path)
        fname=os.path.basename(path)

        if dst[-1]=='/':#if dst is directory then append filename
            fname=dst+fname
        else:
            fname=dst
        _dir=os.path.realpath(os.path.dirname(fname))
        if not os.path.isdir(_dir):
            os.makedirs(_dir)
            
        fh=open(fname,'wb')
        
        total= int(ret.info().get('Content-Length'))#文件总大小
        send=0
        buffer_size=1024
        while True:
            
            if total-send >buffer_size:
                fh.write(ret.read(buffer_size))
                send=send+buffer_size
                progress(total,send)
            else:
                fh.write(ret.read(total-send))
                progress(total,total)
                break
                
        fh.close()
        print('download success')
        print('save to',os.path.abspath(fname))
    
    def get(self,path,dst='./'):
        '''Download a directory or file
           If path is a directory ,it must end with '/'
        '''
        dst='./' if dst==None else dst    

        if path[-1]=='/':
            info=self.api.metadata(path)
            for f in info['files']:
                if f['type']=='folder':
                    self.get(path+f['name']+'/',dst+f['name']+'/')
                else:
                    self.download(path+f['name'],dst)
        else:
            self.download(path,dst)
        
    def f(self,size,unit='A'):
        """格式化大小显示"""
        size=int(size)
        un={'G':3,'M':2, 'K':1}
        if unit=='A':
            if size<1024**2:
                unit='K'
            elif size<1024**3:
                unit='M'
            else :
                unit='G'
        return ("%s%s"%(round(size/float(1024**un[unit]),2),unit))